package com.eduagent.xwqeduagent.controller;

import com.eduagent.xwqeduagent.api.speechsynthesis.api.SpeechSynthesisService;
import com.eduagent.xwqeduagent.api.speechsynthesis.api.SpeechSynthesisUtil;
import com.eduagent.xwqeduagent.api.speechsynthesis.api.constant.Constants;
import com.eduagent.xwqeduagent.api.speechsynthesis.api.constant.ErrorCode;
import com.eduagent.xwqeduagent.api.speechsynthesis.api.exception.SpeechSynthesisException;
import com.eduagent.xwqeduagent.api.speechsynthesis.api.model.ErrorResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import jakarta.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import com.eduagent.xwqeduagent.utils.CosUtils;
import com.eduagent.xwqeduagent.utils.SpringContextUtils;

/**
 * 语音合成API控制器
 * 提供RESTful接口进行文本到语音的转换
 */
@RestController
@RequestMapping("/speech")
public class SpeechSynthesisController {
    
    // 记录每个任务的状态，用于前端轮询
    private static final ConcurrentHashMap<String, TaskStatus> taskStatusMap = new ConcurrentHashMap<>();
    
    // 记录任务ID与生成的音频文件的映射关系
    private static final ConcurrentHashMap<String, String> taskFileMap = new ConcurrentHashMap<>();
    
    @Value("${speech.output.dir:src/main/resources/speech_output}")
    private String outputDirectory;
    
    /**
     * 初始化方法，确保输出目录存在
     */
    @PostConstruct
    public void init() {
        // 创建输出目录（如果不存在）
        File directory = new File(outputDirectory);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        
        // 初始化常量（实际应用中应通过配置文件或环境变量设置）
        Constants.APP_ID = "637d1630";
        Constants.API_KEY = "8bd0514cb66802c719bbf34a908a0119";
        Constants.API_SECRET = "NzUyY2Y3OTYwYjAyMGExODc5OTM1ZGZl";
    }
    
    /**
     * 获取支持的发音人列表
     */
    @GetMapping("/voices")
    public ResponseEntity<Map<String, Object>> getVoiceList() {
        Map<String, Object> response = new HashMap<>();
        response.put("voices", SpeechSynthesisUtil.getVoiceList());
        return ResponseEntity.ok(response);
    }
    
    /**
     * 基本的语音合成接口
     * @param request 合成请求参数
     * @return 任务ID，用于后续查询结果
     */
    @PostMapping("/synthesize")
    public ResponseEntity<Map<String, Object>> synthesizeSpeech(@RequestBody SynthesisRequest request) {
        // 验证请求参数
        if (request.getText() == null || request.getText().trim().isEmpty()) {
            throw SpeechSynthesisException.inputError("合成文本不能为空");
        }
        
        if (request.getText().length() > 8000) {
            throw SpeechSynthesisException.inputError("合成文本长度超过限制，最大支持8000字节");
        }
        
        String taskId = UUID.randomUUID().toString();
        String outputFilePath = outputDirectory + File.separator + taskId + ".mp3";
        
        // 检验发音人参数
        if (request.getVoiceName() == null || request.getVoiceName().trim().isEmpty()) {
            request.setVoiceName("x4_lingxiaoxuan_oral"); // 默认发音人
        }
        
        // 验证发音人是否存在（这里可以用一个方法来验证）
        boolean isValidVoice = false;
        String[] voices = SpeechSynthesisUtil.getVoiceList();
        for (String voice : voices) {
            if (voice.startsWith(request.getVoiceName())) {
                isValidVoice = true;
                break;
            }
        }
        
        if (!isValidVoice) {
            throw SpeechSynthesisException.parameterError("不支持的发音人: " + request.getVoiceName());
        }
        
        // 更新任务状态为处理中
        TaskStatus taskStatus = new TaskStatus(taskId, TaskState.PROCESSING);
        taskStatusMap.put(taskId, taskStatus);
        taskFileMap.put(taskId, outputFilePath);
        
        // 异步处理语音合成
        CompletableFuture.runAsync(() -> {
            try {
                SpeechSynthesisService service = new SpeechSynthesisService(
                        outputFilePath,
                        request.getVoiceName(),
                        new SpeechSynthesisService.SpeechCallback() {
                            @Override
                            public void onSuccess(File audioFile) {
                                taskStatus.setState(TaskState.COMPLETED);
                            }

                            @Override
                            public void onError(int code, String message) {
                                taskStatus.setState(TaskState.FAILED);
                                taskStatus.setErrorMessage("合成失败: " + message + ", 错误码: " + code);
                                taskStatus.setErrorCode(code);
                            }
                        }
                );
                service.synthesize(request.getText());
            } catch (Exception e) {
                taskStatus.setState(TaskState.FAILED);
                taskStatus.setErrorMessage("处理异常: " + e.getMessage());
                taskStatus.setErrorCode(ErrorCode.ENGINE_EXCEPTION);
            }
        });
        
        Map<String, Object> response = new HashMap<>();
        response.put("taskId", taskId);
        response.put("status", "processing");
        
        return ResponseEntity.accepted().body(response);
    }
    
    /**
     * 高级语音合成接口（支持多音字和停顿）
     * @param request 高级合成请求参数
     * @return 任务ID，用于后续查询结果
     */
    @PostMapping("/synthesize/advanced")
    public ResponseEntity<Map<String, Object>> synthesizeAdvanced(@RequestBody AdvancedSynthesisRequest request) {
        // 验证请求参数
        if (request.getText() == null || request.getText().trim().isEmpty()) {
            throw SpeechSynthesisException.inputError("合成文本不能为空");
        }
        
        if (request.getText().length() > 8000) {
            throw SpeechSynthesisException.inputError("合成文本长度超过限制，最大支持8000字节");
        }
        
        String taskId = UUID.randomUUID().toString();
        String outputFilePath = outputDirectory + File.separator + taskId + ".mp3";
        
        // 处理文本中的特殊标记
        String processedText = request.getText();
        
        // 处理多音字
        if (request.getPronunciations() != null) {
            for (Map.Entry<Integer, String> entry : request.getPronunciations().entrySet()) {
                try {
                    processedText = SpeechSynthesisUtil.setPronunciation(
                            processedText, entry.getKey(), entry.getValue());
                } catch (IllegalArgumentException e) {
                    throw SpeechSynthesisException.parameterError("多音字设置错误: " + e.getMessage());
                }
            }
        }
        
        // 处理停顿
        if (request.getPauses() != null) {
            for (Map.Entry<Integer, Integer> entry : request.getPauses().entrySet()) {
                // 在指定位置插入停顿
                int position = entry.getKey();
                int duration = entry.getValue();
                
                if (position < 0 || position > processedText.length()) {
                    throw SpeechSynthesisException.parameterError("停顿位置无效: " + position + 
                            "，应在0到" + processedText.length() + "之间");
                }
                
                if (duration <= 0) {
                    throw SpeechSynthesisException.parameterError("停顿时长必须大于0: " + duration);
                }
                
                processedText = processedText.substring(0, position) + 
                        "[p" + duration + "]" + 
                        processedText.substring(position);
            }
        }
        
        // 创建任务状态
        TaskStatus taskStatus = new TaskStatus(taskId, TaskState.PROCESSING);
        taskStatusMap.put(taskId, taskStatus);
        taskFileMap.put(taskId, outputFilePath);
        
        // 设置默认发音人
        if (request.getVoiceName() == null || request.getVoiceName().trim().isEmpty()) {
            request.setVoiceName("x4_lingxiaoxuan_oral");
        }
        
        // 验证发音人是否存在
        boolean isValidVoice = false;
        String[] voices = SpeechSynthesisUtil.getVoiceList();
        for (String voice : voices) {
            if (voice.startsWith(request.getVoiceName())) {
                isValidVoice = true;
                break;
            }
        }
        
        if (!isValidVoice) {
            throw SpeechSynthesisException.parameterError("不支持的发音人: " + request.getVoiceName());
        }
        
        // 异步处理
        final String finalText = processedText;
        CompletableFuture.runAsync(() -> {
            try {
                SpeechSynthesisService service = new SpeechSynthesisService(
                        outputFilePath,
                        request.getVoiceName(),
                        new SpeechSynthesisService.SpeechCallback() {
                            @Override
                            public void onSuccess(File audioFile) {
                                taskStatus.setState(TaskState.COMPLETED);
                            }

                            @Override
                            public void onError(int code, String message) {
                                taskStatus.setState(TaskState.FAILED);
                                taskStatus.setErrorMessage("合成失败: " + message + ", 错误码: " + code);
                                taskStatus.setErrorCode(code);
                            }
                        }
                );
                service.synthesize(finalText);
            } catch (Exception e) {
                taskStatus.setState(TaskState.FAILED);
                taskStatus.setErrorMessage("处理异常: " + e.getMessage());
                taskStatus.setErrorCode(ErrorCode.ENGINE_EXCEPTION);
            }
        });
        
        Map<String, Object> response = new HashMap<>();
        response.put("taskId", taskId);
        response.put("status", "processing");
        response.put("processedText", processedText);
        
        return ResponseEntity.accepted().body(response);
    }
    
    /**
     * 查询任务状态
     * @param taskId 任务ID
     * @return 任务状态
     */
    @GetMapping("/status/{taskId}")
    public ResponseEntity<Map<String, Object>> getTaskStatus(@PathVariable String taskId) {
        TaskStatus status = taskStatusMap.get(taskId);
        if (status == null) {
            throw new SpeechSynthesisException(ErrorCode.LB_NODE_NOT_FOUND, "任务不存在: " + taskId, taskId);
        }
        
        Map<String, Object> response = new HashMap<>();
        response.put("taskId", taskId);
        response.put("status", status.getState().name().toLowerCase());
        
        if (status.getState() == TaskState.FAILED && status.getErrorMessage() != null) {
            response.put("errorMessage", status.getErrorMessage());
            response.put("errorCode", status.getErrorCode());
        }
        
        return ResponseEntity.ok(response);
    }
    
    /**
     * 下载生成的音频文件
     * @param taskId 任务ID
     * @return 音频文件
     */
    @GetMapping("/download/{taskId}")
    public ResponseEntity<Resource> downloadAudio(@PathVariable String taskId) {
        TaskStatus status = taskStatusMap.get(taskId);
        if (status == null) {
            throw new SpeechSynthesisException(ErrorCode.LB_NODE_NOT_FOUND, "任务不存在: " + taskId, taskId);
        }
        
        if (status.getState() != TaskState.COMPLETED) {
            throw new SpeechSynthesisException(ErrorCode.PARAMETER_ERROR, 
                    "任务未完成，当前状态: " + status.getState().name().toLowerCase(), taskId);
        }
        
        String filePath = taskFileMap.get(taskId);
        if (filePath == null) {
            throw new SpeechSynthesisException(ErrorCode.LB_NODE_NOT_FOUND, "文件不存在", taskId);
        }
        
        try {
            Path path = Paths.get(filePath);
            Resource resource = new InputStreamResource(new FileInputStream(path.toFile()));
            
            // 定义HTTP响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", taskId + ".mp3");
            
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(Files.size(path))
                    .body(resource);
                    
        } catch (IOException e) {
            throw new SpeechSynthesisException(ErrorCode.ENGINE_EXCEPTION, "文件读取失败: " + e.getMessage(), taskId);
        }
    }
    
    /**
     * 解析带有标记的文本
     * @param request 解析请求
     * @return 解析结果
     */
    @PostMapping("/parse")
    public ResponseEntity<Map<String, Object>> parseMarkedText(@RequestBody ParseRequest request) {
        if (request.getText() == null) {
            throw SpeechSynthesisException.inputError("解析文本不能为空");
        }
        
        String result = SpeechSynthesisUtil.parseMarkedText(request.getText());
        
        Map<String, Object> response = new HashMap<>();
        response.put("text", request.getText());
        response.put("parseResult", result);
        
        return ResponseEntity.ok(response);
    }
    
    /**
     * 清理已完成的任务
     * @param taskId 任务ID
     * @return 清理结果
     */
    @DeleteMapping("/tasks/{taskId}")
    public ResponseEntity<Map<String, Object>> cleanupTask(@PathVariable String taskId) {
        TaskStatus status = taskStatusMap.get(taskId);
        if (status == null) {
            throw new SpeechSynthesisException(ErrorCode.LB_NODE_NOT_FOUND, "任务不存在: " + taskId, taskId);
        }
        
        // 删除文件和任务记录
        String filePath = taskFileMap.get(taskId);
        if (filePath != null) {
            try {
                Files.deleteIfExists(Paths.get(filePath));
            } catch (IOException e) {
                // 记录错误但不抛出异常
                System.err.println("删除文件失败: " + e.getMessage());
            }
        }
        
        taskStatusMap.remove(taskId);
        taskFileMap.remove(taskId);
        
        Map<String, Object> response = new HashMap<>();
        response.put("taskId", taskId);
        response.put("result", "任务已清理");
        
        return ResponseEntity.ok(response);
    }
    
    /**
     * 将生成的音频文件上传到COS并返回URL
     * @param taskId 任务ID
     * @return 音频文件的COS URL
     */
    @GetMapping("/upload-to-cos/{taskId}")
    public ResponseEntity<Map<String, Object>> uploadToCos(@PathVariable String taskId) {
        // 检查任务状态
        TaskStatus status = taskStatusMap.get(taskId);
        if (status == null) {
            throw new SpeechSynthesisException(ErrorCode.LB_NODE_NOT_FOUND, "任务不存在: " + taskId, taskId);
        }
        
        if (status.getState() != TaskState.COMPLETED) {
            throw new SpeechSynthesisException(ErrorCode.PARAMETER_ERROR, 
                    "任务未完成，当前状态: " + status.getState().name().toLowerCase(), taskId);
        }
        
        // 获取文件路径
        String filePath = taskFileMap.get(taskId);
        if (filePath == null) {
            throw new SpeechSynthesisException(ErrorCode.LB_NODE_NOT_FOUND, "文件不存在", taskId);
        }
        
        try {
            // 获取文件
            File audioFile = new File(filePath);
            if (!audioFile.exists()) {
                throw new SpeechSynthesisException(ErrorCode.ENGINE_EXCEPTION, "文件不存在: " + filePath, taskId);
            }
            
            // 注入CosUtils
            CosUtils cosUtils = SpringContextUtils.getBean(CosUtils.class);
            
            // 上传到COS，使用"speech_synthesis"作为目录
            String fileUrl = cosUtils.uploadFile(audioFile, "speech_synthesis");
            
            Map<String, Object> response = new HashMap<>();
            response.put("taskId", taskId);
            response.put("status", "success");
            response.put("url", fileUrl);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            throw new SpeechSynthesisException(ErrorCode.ENGINE_EXCEPTION, "上传文件失败: " + e.getMessage(), taskId);
        }
    }
    
    /**
     * 任务状态枚举
     */
    private enum TaskState {
        PROCESSING,
        COMPLETED,
        FAILED
    }
    
    /**
     * 任务状态类
     */
    private static class TaskStatus {
        private String taskId;
        private TaskState state;
        private String errorMessage;
        private int errorCode;
        
        public TaskStatus(String taskId, TaskState state) {
            this.taskId = taskId;
            this.state = state;
        }
        
        public String getTaskId() {
            return taskId;
        }
        
        public TaskState getState() {
            return state;
        }
        
        public void setState(TaskState state) {
            this.state = state;
        }
        
        public String getErrorMessage() {
            return errorMessage;
        }
        
        public void setErrorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
        }
        
        public int getErrorCode() {
            return errorCode;
        }
        
        public void setErrorCode(int errorCode) {
            this.errorCode = errorCode;
        }
    }
    
    /**
     * 基本合成请求
     */
    public static class SynthesisRequest {
        private String text;
        private String voiceName;
        
        public String getText() {
            return text;
        }
        
        public void setText(String text) {
            this.text = text;
        }
        
        public String getVoiceName() {
            return voiceName;
        }
        
        public void setVoiceName(String voiceName) {
            this.voiceName = voiceName;
        }
    }
    
    /**
     * 高级合成请求
     */
    public static class AdvancedSynthesisRequest extends SynthesisRequest {
        // Map<位置, 发音>
        private Map<Integer, String> pronunciations;
        
        // Map<位置, 停顿时长>
        private Map<Integer, Integer> pauses;
        
        public Map<Integer, String> getPronunciations() {
            return pronunciations;
        }
        
        public void setPronunciations(Map<Integer, String> pronunciations) {
            this.pronunciations = pronunciations;
        }
        
        public Map<Integer, Integer> getPauses() {
            return pauses;
        }
        
        public void setPauses(Map<Integer, Integer> pauses) {
            this.pauses = pauses;
        }
    }
    
    /**
     * 文本解析请求
     */
    public static class ParseRequest {
        private String text;
        
        public String getText() {
            return text;
        }
        
        public void setText(String text) {
            this.text = text;
        }
    }
} 